home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
rayshade
/
rayview
/
glmethods.c
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
21KB
|
1,037 lines
/*
* glmethods.c
*
* Support routines for SGI/RS6000 machines.
*
* Copyright (C) 1989, 1991, Craig E. Kolb, Allan Snyder
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
* $Id: glmethods.c,v 4.0.1.4 92/01/10 17:17:39 cek Exp Locker: cek $
*
* $Log: glmethods.c,v $
* Revision 4.0.1.4 92/01/10 17:17:39 cek
* patch3: Added heightfield support.
*
* Revision 4.0.1.3 91/12/13 11:43:11 cek
* patch3: Spot direction and spread now set correctly.
* patch3: Set GLC_OLDPOLYGON to 0 on sgi machines to fix VGX weirdness.
*
* Revision 4.0.1.2 91/10/10 22:45:27 cek
* patch1: Added spotlight support.
*
* Revision 4.0.1.1 1991/09/29 15:28:36 cek
* patch1: Added support for transparency.
*
* Revision 4.0 91/07/17 17:38:43 kolb
* Initial version
*
*/
#include <gl.h>
#include <device.h>
#include "rayshade.h"
#include "options.h"
#include "viewing.h"
#include "libsurf/surface.h"
#include "libobj/box.h"
#include "libobj/cone.h"
#include "libobj/csg.h"
#include "libobj/cylinder.h"
#include "libobj/disc.h"
#include "libobj/hf.h"
#include "libobj/grid.h"
#include "libobj/instance.h"
#include "libobj/list.h"
#include "libobj/plane.h"
#include "libobj/poly.h"
#include "libobj/sphere.h"
#include "libobj/triangle.h"
#include "liblight/light.h"
#include "liblight/extended.h"
#include "liblight/infinite.h"
#include "liblight/point.h"
#include "liblight/spot.h"
#define CIRCLE_SAMPLES 20 /* # of samples around circle (cone/cyl/etc) */
#define DEFAULT_NEAR .2 /* default value for near clipping plane */
#define DEFAULT_FAR 350. /* default far clipping plane */
#define PLANE_RAD 450. /* radius of disc used to represent planes */
#ifndef SPHERELIB
#define SPHERE_LEVEL 3
#endif
/*
* Pass a normal stored in a Vector to the geometry pipeline.
*/
#define GLNormal(w) (glnrm[0] = (w)->x, glnrm[1] = (w)->y, \
glnrm[2] = (w)->z, n3f(glnrm))
static void GLBoxDraw(), GLConeDraw(), GLCsgDraw(), GLCylinderDraw(),
GLDiscDraw(),
GLGridDraw(), GLHfDraw(), GLInstanceDraw(),
GLListDraw(), GLPlaneDraw(), GLPolygonDraw(),
GLSphereDraw(), GLTorusDraw(), GLTriangleDraw(),
GLBoundsDraw(),
GLInfiniteLight(), GLPointLight(), GLSpotLight(),
GLExtendedLight();
static short cursurf = 1,
curlight = 1;
static Object GLBoxObject,
GLCylObject,
GLSphereObject,
GLBoxObjectDefine(),
GLCylObjectDefine();
extern Object GLSphereObjectDefine();
static int Doublebuffered;
static float Ident[4][4] = {1., 0., 0., 0.,
0., 1., 0., 0.,
0., 0., 1., 0.,
0., 0., 0., 1.},
glnrm[3];
static float **CirclePoints;
static void LightDraw(), GeomDraw(), GLMultMatrix(),
GLPushSurface(), GLPopSurface(), LightDrawInit(),
ObjectInit(), GLDrawFrame(), ScreenDrawInit(), DrawInit(),
GLUnitCircle(), GLDisc(), ComputeClippingPlanes();
Float CurrentTime;
static unsigned long BackPack; /* Packed background color */
static long Zinit; /* maximum Zbuffer value */
MethodsRegister()
{
BoxMethodRegister(GLBoxDraw);
ConeMethodRegister(GLConeDraw);
CsgMethodRegister(GLCsgDraw);
CylinderMethodRegister(GLCylinderDraw);
DiscMethodRegister(GLDiscDraw);
GridMethodRegister(GLGridDraw);
#ifdef sgi
HfMethodRegister(GLHfDraw);
#endif
InstanceMethodRegister(GLInstanceDraw);
ListMethodRegister(GLListDraw);
PlaneMethodRegister(GLPlaneDraw);
PolygonMethodRegister(GLPolygonDraw);
SphereMethodRegister(GLSphereDraw);
/*TorusMethodRegister(GLTorusDraw);*/
TriangleMethodRegister(GLTriangleDraw);
InfiniteMethodRegister(GLInfiniteLight);
PointMethodRegister(GLPointLight);
ExtendedMethodRegister(GLExtendedLight);
SpotMethodRegister(GLSpotLight);
}
void
Render()
{
short val;
float tmp;
/*
* We're only sampling the scene once, so we need
* not do lots of work to determine exactly what
* animated transformations are doing...
*/
Options.samples = 1;
SamplingSetOptions(Options.samples, Options.gaussian,
Options.filterwidth);
DrawInit();
qdevice(ESCKEY);
qdevice(SPACEKEY);
qdevice(REDRAW);
DrawFrames();
while (TRUE) {
switch (qread(&val)) {
case ESCKEY:
exit(0);
break;
case REDRAW:
reshapeviewport();
DrawFrames();
break;
case SPACEKEY:
if (!val)
DrawFrames();
break;
}
}
}
DrawFrames()
{
int i;
for (i = 0; i < Options.totalframes; i++)
GLDrawFrame(i);
}
static void
DrawInit()
{
extern Surface DefaultSurface;
ScreenDrawInit();
ObjectInit();
LightDrawInit();
/*
* Push the default surface.
*/
GLPushSurface(&DefaultSurface);
}
static void
ScreenDrawInit()
{
/*
* Open window, initialize graphics, etc.
*/
#ifdef sgi
foreground();
#endif
prefsize(Screen.xsize, Screen.ysize);
winopen("rayview");
#ifdef sgi
glcompat(GLC_OLDPOLYGON, 0);
#endif
RGBmode();
mmode(MVIEWING);
if (Options.totalframes > 1) {
Doublebuffered = TRUE;
doublebuffer();
}
gconfig();
blendfunction(BF_SA, BF_MSA);
zbuffer(TRUE);
/*
* Initialize viewing matrix.
*/
GLViewingInit();
BackPack = (unsigned char)(255*Screen.background.r) |
((unsigned char)(255*Screen.background.g) << 8) |
((unsigned char)(255*Screen.background.b) << 16);
Zinit = getgdesc(GD_ZMAX);
lsetdepth(0, Zinit);
}
/*
* Draw the World object.
*/
static void
GLDrawFrame(frame)
int frame;
{
extern Geom *World;
RSStartFrame(frame);
CurrentTime = Options.framestart;
TimeSet(CurrentTime);
czclear(BackPack, Zinit);
/*
* Draw the World object
*/
GeomDraw(World);
if (Doublebuffered)
swapbuffers();
}
GLViewingInit()
{
float near, far, aspect, dist, T[4][4];
short ang;
extern Geom *World;
ang = Camera.vfov * 10 + 0.5;
aspect = Camera.hfov / Camera.vfov;
T[0][0]=Screen.scrni.x; T[0][1]=Screen.scrnj.x; T[0][2]= -Camera.dir.x;
T[1][0]=Screen.scrni.y; T[1][1]=Screen.scrnj.y; T[1][2]= -Camera.dir.y;
T[2][0]=Screen.scrni.z; T[2][1]=Screen.scrnj.z; T[2][2]= -Camera.dir.z;
T[0][3] = T[1][3] = T[2][3] = 0.;
T[3][0] = -dotp(&Camera.lookp, &Screen.scrni);
T[3][1] = -dotp(&Camera.lookp, &Screen.scrnj);
T[3][2] = dotp(&Camera.lookp, &Camera.dir);
T[3][3] = 1.;
ComputeClippingPlanes(&near, &far, World->bounds);
loadmatrix(Ident);
perspective(ang, aspect, near, far);
polarview((float)Camera.lookdist, 0, 0, 0);
multmatrix(T);
}
static void
ObjectInit()
{
CircleDefine();
GLBoxObject = GLBoxObjectDefine();
#ifdef SPHERELIB
GLSphereObject = GLSphereObjectDefine();
#else
GLSphereObject = GLSphereObjectDefine(SPHERE_LEVEL);
#endif
GLCylObject = GLCylObjectDefine();
}
static void
GeomDraw(obj)
Geom *obj;
{
Trans *ct;
/*
* If object has a surface associated with it,
* start using it.
*/
if (obj->surf)
GLPushSurface(obj->surf);
if (obj->trans) {
/*
* Take care of any animated transformations that
* exist.
*/
if (obj->animtrans && !equal(obj->timenow, CurrentTime)) {
TransResolveAssoc(obj->trans);
obj->timenow = CurrentTime;
}
pushmatrix();
/*
* Apply in reverse order.
*/
for (ct = obj->transtail; ct; ct = ct->prev)
GLMultMatrix(&ct->trans);
}
if (obj->methods->user) {
/*
* Call proper method
*/
(*obj->methods->user)(obj->obj);
} else {
/*
* Draw bounding box.
*/
GLBoundsDraw(obj->bounds);
}
if (obj->surf)
GLPopSurface();
if (obj->trans)
popmatrix();
}
static float surfprops[] = {AMBIENT, 0, 0, 0,
DIFFUSE, 0, 0, 0,
SPECULAR, 0, 0, 0,
SHININESS, 0,
ALPHA, 1,
LMNULL};
static float *amb = &surfprops[1],
*diff = &surfprops[5],
*spec = &surfprops[9],
*shine = &surfprops[13],
*alpha = &surfprops[15];
static void
GLPushSurface(surf)
Surface *surf;
{
static Surface *lastsurf = NULL;
/*
* Start using the given surface.
* In the case of the use of an "applysurf",
* the same surface will be applied to many
* primitives individually. By saving the
* pointer to the last surface, we keep from
* lmdef'ing the surface when we don't need to.
*/
if (surf != lastsurf) {
amb[0] = surf->amb.r; amb[1] = surf->amb.g;
amb[2] = surf->amb.b;
diff[0] = surf->diff.r; diff[1] = surf->diff.g;
diff[2] = surf->diff.b;
spec[0] = surf->spec.r; spec[1] = surf->spec.g;
spec[2] = surf->spec.b;
shine[0] = surf->srexp;
*alpha = 1. - surf->transp;
lmdef(DEFMATERIAL, cursurf, sizeof(surfprops)/sizeof(float),
surfprops);
lastsurf = surf;
}
lmbind(MATERIAL, cursurf);
cursurf++;
}
static void
GLMultMatrix(trans)
RSMatrix *trans;
{
float newmat[4][4];
/*
* Multiply in the given transformation.
*/
newmat[0][0] = trans->matrix[0][0]; newmat[0][1] = trans->matrix[0][1];
newmat[0][2] = trans->matrix[0][2]; newmat[0][3] = 0.;
newmat[1][0] = trans->matrix[1][0]; newmat[1][1] = trans->matrix[1][1];
newmat[1][2] = trans->matrix[1][2]; newmat[1][3] = 0.;
newmat[2][0] = trans->matrix[2][0]; newmat[2][1] = trans->matrix[2][1];
newmat[2][2] = trans->matrix[2][2]; newmat[2][3] = 0.;
newmat[3][0] = trans->translate.x; newmat[3][1] = trans->translate.y;
newmat[3][2] = trans->translate.z ; newmat[3][3] = 1.;
multmatrix(newmat);
}
static void
GLPopSurface()
{
cursurf--;
lmbind(MATERIAL, cursurf-1);
}
static void
GLBoundsDraw(bounds)
Float bounds[2][3];
{
float sx, sy, sz;
pushmatrix();
translate(bounds[LOW][X], bounds[LOW][Y], bounds[LOW][Z]);
scale( bounds[HIGH][X] - bounds[LOW][X],
bounds[HIGH][Y] - bounds[LOW][Y],
bounds[HIGH][Z] - bounds[LOW][Z]);
pushmatrix();
callobj(GLBoxObject);
popmatrix();
popmatrix();
}
static void
GLBoxDraw(box)
Box *box;
{
GLBoundsDraw(box->bounds);
}
static void
GLConeDraw(cone)
Cone *cone;
{
int i, j;
float norm[3], normconst, ZeroVect[3], tmpv[3];
ZeroVect[0] = ZeroVect[1] = ZeroVect[2] = 0.;
/*
* Sides.
* For the normal, assume we are finding the normal at
* (C_P[i].x, C_P[i].y, 1.) at this point, the unnormalized
* normal = (C_P[i].x, C_P[i].y, -tantheta^2). When we normalize,
* then length of the vector is simply equal to:
* sqrt(CP[i].x^2 + CP[i].y^2 + tantheta^4) ==
* sqrt(1. + tantheta^4)
* In our case, tantheta = 1., so...
*/
normconst = 1. / sqrt(2.);
norm[2] = -normconst;
pushmatrix();
GLMultMatrix(&cone->trans.trans);
for (i = 0; i < CIRCLE_SAMPLES; i++) {
j = (i + 1) % CIRCLE_SAMPLES;
norm[0] = CirclePoints[i][0] * normconst;
norm[1] = CirclePoints[i][1] * normconst;
n3f(norm);
bgnpolygon();
if (cone->start_dist > EPSILON) {
tmpv[2] = cone->start_dist;
tmpv[0] = CirclePoints[i][0] * cone->start_dist;
tmpv[1] = CirclePoints[i][1] * cone->start_dist;
v3f(tmpv);
tmpv[0] = CirclePoints[j][0] * cone->start_dist;
tmpv[1] = CirclePoints[j][1] * cone->start_dist;
v3f(tmpv);
} else
v3f(ZeroVect);
tmpv[2] = 1.;
tmpv[0] = CirclePoints[j][0];
tmpv[1] = CirclePoints[j][1];
v3f(tmpv);
tmpv[0] = CirclePoints[i][0];
tmpv[1] = CirclePoints[i][1];
v3f(tmpv);
endpolygon();
}
popmatrix();
}
static void
GLCsgDraw(csg)
Csg *csg;
{
/*
* Punt by drawing both objects.
*/
GeomDraw(csg->obj1);
GeomDraw(csg->obj2);
}
static void
GLCylinderDraw(cyl)
Cylinder *cyl;
{
pushmatrix();
GLMultMatrix(&cyl->trans.trans);
callobj(GLCylObject);
popmatrix();
}
static void
GLDiscDraw(disc)
Disc *disc;
{
GLDisc((Float)sqrt(disc->radius), &disc->pos, &disc->norm);
}
static void
GLDisc(rad, pos, norm)
Float rad;
Vector *pos, *norm;
{
RSMatrix m, tmp;
Vector atmp;
/*
* This is kinda disgusting...
*/
ScaleMatrix(rad, rad, 1., &m);
if (fabs(norm->z) == 1.) {
atmp.x = 1.;
atmp.y = atmp.z = 0.;
} else {
atmp.x = norm->y;
atmp.y = -norm->x;
atmp.z= 0.;
}
RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(norm->z), &tmp);
MatrixMult(&m, &tmp, &m);
TranslationMatrix(pos->x, pos->y, pos->z, &tmp);
MatrixMult(&m, &tmp, &m);
pushmatrix();
GLMultMatrix(&m);
/*
* Draw unit circle.
*/
GLUnitCircle(0., TRUE);
popmatrix();
}
static void
GLGridDraw(grid)
Grid *grid;
{
Geom *ltmp;
for (ltmp = grid->unbounded; ltmp; ltmp = ltmp->next)
GeomDraw(ltmp);
for (ltmp = grid->objects; ltmp; ltmp = ltmp->next)
GeomDraw(ltmp);
}
static void
GLHfDraw(hf)
Hf *hf;
{
int x, y;
float n[3], v[3], del, del2, del4, dz1, delz, za, zb, zc;
float bot, top, left, right, len;
del = 1. / (hf->size - 1);
del2 = del*del;
del4 = del2*del2;
bot = 0.;
top = del;
for (y = 0; y < hf->size -1; y++) {
za = hf->data[y+1][0];
zb = hf->data[y][0];
left = 0;
right = del;
for (x = 1; x < hf->size; x++) {
/*
* A +-+ C
* |/
* B +
*/
zc = hf->data[y+1][x];
dz1 = za - zb;
delz = za - zc;
len = sqrt(del2*delz*delz + del2*dz1*dz1 + del4);
bgnpolygon();
n[0] = del*delz/len;
n[1] = -del*dz1/len;
n[2] = del2/len;
n3f(n);
v[0] = left; v[1] = top; v[2] = za; v3f(v);
v[1] = bot; v[2] = zb; v3f(v);
v[0] = right; v[1] = top; v[2] = zc; v3f(v);
endpolygon();
/*
* B +
* /|
* A +-+ C
*/
za = zb; zb = zc; zc = hf->data[y][x];
dz1 = zc - za;
delz = zc - zb;
len = sqrt(del2*dz1*dz1 + del2*delz*delz + del4);
n[0] = -del*dz1/len;
n[1] = del*delz/len;
n[2] = del2/len;
bgnpolygon();
n3f(n);
v[0] = left; v[1] = bot; v[2] = za; v3f(v);
v[0] = right; v[2] = zc; v3f(v);
v[1] = top; v[2] = zb; v3f(v);
endpolygon();
left = right;
right += del;
za = zb;
zb = zc;
}
bot = top;
top += del;
}
}
static void
GLInstanceDraw(inst)
Instance *inst;
{
GeomDraw(inst->obj);
}
static void
GLListDraw(list)
List *list;
{
Geom *ltmp;
for (ltmp = list->unbounded; ltmp; ltmp = ltmp->next)
GeomDraw(ltmp);
for (ltmp = list->list; ltmp; ltmp = ltmp->next)
GeomDraw(ltmp);
}
static void
GLPlaneDraw(plane)
Plane *plane;
{
/*
* Draw a really big disc.
*/
GLDisc((Float)PLANE_RAD, &plane->pos, &plane->norm);
}
static void
GLPolygonDraw(poly)
register Polygon *poly;
{
register int i;
GLNormal(&poly->norm);
bgnpolygon();
for (i = 0; i < poly->npoints; i++)
v3d(&poly->points[i]);
endpolygon();
}
static void
GLSphereDraw(sph)
Sphere *sph;
{
pushmatrix();
translate(sph->x, sph->y, sph->z);
scale(sph->r, sph->r, sph->r);
callobj(GLSphereObject);
popmatrix();
}
static void
GLTorusDraw(){}
static void
GLTriangleDraw(tri)
register Triangle *tri;
{
/*
* If Float is a double, use v3d,
* otherwise use v3f.
*/
if (tri->type != PHONGTRI) {
GLNormal(&tri->nrm);
bgnpolygon();
v3d(&tri->p[0]); v3d(&tri->p[1]); v3d(&tri->p[2]);
endpolygon();
} else {
bgnpolygon();
GLNormal(&tri->vnorm[0]);
v3d(&tri->p[0]);
GLNormal(&tri->vnorm[1]);
v3d(&tri->p[1]);
GLNormal(&tri->vnorm[2]);
v3d(&tri->p[2]);
endpolygon();
}
}
float lightprops[] = {POSITION, 0., 0., 0., 0.,
LCOLOR, 0, 0, 0,
SPOTDIRECTION, 0., 0., 0.,
SPOTLIGHT, 0., 180.,
LMNULL};
float *lpos = &lightprops[1],
*lcolor = &lightprops[6],
*spotdir = &lightprops[10],
*spotexp = &lightprops[14],
*spotspread = &lightprops[15];
float lmodel[] = {AMBIENT, 1., 1., 1.,
ATTENUATION, 1., 0.,
LOCALVIEWER, 0.,
#ifdef sgi
ATTENUATION2, 0.,
TWOSIDE, 1.,
#endif
LMNULL};
static void
LightDrawInit()
{
Light *light;
extern Light *Lights;
for (light = Lights; light; light = light->next)
LightDraw(light);
switch (curlight-1) {
case 8:
lmbind(LIGHT7, 8);
case 7:
lmbind(LIGHT6, 7);
case 6:
lmbind(LIGHT5, 6);
case 5:
lmbind(LIGHT4, 5);
case 4:
lmbind(LIGHT3, 4);
case 3:
lmbind(LIGHT2, 3);
case 2:
lmbind(LIGHT1, 2);
case 1:
lmbind(LIGHT0, 1);
}
lmodel[1] = Options.ambient.r;
lmodel[2] = Options.ambient.g;
lmodel[3] = Options.ambient.b;
lmdef(DEFLMODEL, 1, sizeof(lmodel) / sizeof(float), lmodel);
lmbind(LMODEL, 1);
}
static void
LightDraw(light)
Light *light;
{
if (!light || !light->methods->user)
return;
lcolor[0] = light->color.r;
lcolor[1] = light->color.g;
lcolor[2] = light->color.b;
(*light->methods->user)(light->light);
}
static void
GLExtendedLight(ext)
Extended *ext;
{
lpos[0] = ext->pos.x;
lpos[1] = ext->pos.y;
lpos[2] = ext->pos.z;
lpos[3] = 1.;
lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
lightprops);
}
static void
GLInfiniteLight(inf)
Infinite *inf;
{
lpos[0] = inf->dir.x;
lpos[1] = inf->dir.y;
lpos[2] = inf->dir.z;
lpos[3] = 0.;
lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
lightprops);
}
static void
GLPointLight(pt)
Pointlight *pt;
{
lpos[0] = pt->pos.x;
lpos[1] = pt->pos.y;
lpos[2] = pt->pos.z;
lpos[3] = 1.;
lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
lightprops);
}
static void
GLSpotLight(spot)
Spotlight *spot;
{
lpos[0] = spot->pos.x;
lpos[1] = spot->pos.y;
lpos[2] = spot->pos.z;
lpos[3] = 1.;
spotdir[0] = spot->dir.x;
spotdir[1] = spot->dir.y;
spotdir[2] = spot->dir.z;
*spotexp = spot->coef;
*spotspread = 180 * acos(spot->falloff) / PI;
lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
lightprops);
/* fix up spot defs so other source methods needn't reset them. */
*spotspread = 180.;
*spotexp = 1.;
}
static float boxfaces[6][4][3] = {
{ {1., 1., 1.},
{0., 1., 1.},
{0., 0., 1.},
{1., 0., 1.} },
{ {1., 0., 1.},
{0., 0., 1.},
{0., 0., 0.},
{1., 0., 0.} },
{ {1., 0., 0.},
{0., 0., 0.},
{0., 1., 0.},
{1., 1., 0.} },
{ {0., 1., 0.},
{0., 1., 1.},
{1., 1., 1.},
{1., 1., 0.} },
{ {1., 1., 1.},
{1., 0., 1.},
{1., 0., 0.},
{1., 1., 0.} },
{ {0., 0., 1.},
{0., 1., 1.},
{0., 1., 0.},
{0., 0., 0.}}};
float boxnorms[6][3] = {
{0, 0, 1},
{0, -1, 0},
{0, 0, -1},
{0, 1, 0},
{1, 0, 0,},
{-1, 0, 0}};
/*
* Define a unit cube centered at (0.5, 0.5, 0.5)
*/
static Object
GLBoxObjectDefine()
{
int i, box;
makeobj(box = genobj());
for (i = 0; i < 6; i++) {
n3f(boxnorms[i]);
polf(4, boxfaces[i]);
}
closeobj();
return box;
}
static void
GLUnitCircle(z, up)
float z;
int up;
{
int i;
float norm[3];
norm[0] = norm[1] = 0.;
bgnpolygon();
if (up) {
norm[2] = 1.;
n3f(norm);
for (i = 0; i < CIRCLE_SAMPLES; i++) {
CirclePoints[i][2] = z;
v3f(CirclePoints[i]);
}
} else {
norm[2] = -1.;
n3f(norm);
for (i = CIRCLE_SAMPLES -1; i; i--) {
CirclePoints[i][2] = z;
v3f(CirclePoints[i]);
}
}
endpolygon();
}
static Object
GLCylObjectDefine()
{
int i, j, cyl;
float norm[3];
makeobj(cyl = genobj());
norm[2] = 0;
for (i = 0; i < CIRCLE_SAMPLES; i++) {
j = (i+1)%CIRCLE_SAMPLES;
norm[0] = CirclePoints[i][0];
norm[1] = CirclePoints[i][1];
#ifdef sgi
n3f(norm);
bgnpolygon();
CirclePoints[i][2] = 0;
v3f(CirclePoints[i]);
CirclePoints[j][2] = 0;
v3f(CirclePoints[j]);
CirclePoints[j][2] = 1;
v3f(CirclePoints[j]);
CirclePoints[i][2] = 1;
v3f(CirclePoints[i]);
endpolygon();
#else
n3f(norm);
pmv(CirclePoints[i][0], CirclePoints[i][1], 0.);
pdr(CirclePoints[j][0], CirclePoints[j][1], 0.);
pdr(CirclePoints[j][0], CirclePoints[j][1], 1.);
pdr(CirclePoints[i][0], CirclePoints[i][1], 1.);
pclos();
#endif
}
closeobj();
return cyl;
}
/*
* Fill CirclePoints[t] with X and Y values cooresponding to points
* along the unit circle. The size of CirclePoints is equal to
* CIRCLE_SAMPLES.
*/
CircleDefine()
{
int i;
double theta, dtheta;
dtheta = 2.*M_PI / (double)CIRCLE_SAMPLES;
CirclePoints = (float **)malloc(CIRCLE_SAMPLES * sizeof(float *));
for (i = 0, theta = 0; i < CIRCLE_SAMPLES; i++, theta += dtheta) {
CirclePoints[i] = (float *)malloc(3 * sizeof(float));
CirclePoints[i][0] = cos(theta);
CirclePoints[i][1] = sin(theta);
/* Z is left unset. */
}
}
/*
* Given world bounds, determine near and far
* clipping planes. Only problem occurs when there are
* unbbounded objects (planes)...
*/
static void
ComputeClippingPlanes(near, far, bounds)
float *near, *far;
Float bounds[2][3];
{
Vector e, c;
double rad, d;
/*
* Compute 'radius' of scene.
*/
rad = max(max((bounds[HIGH][X] - bounds[LOW][X])*0.5,
(bounds[HIGH][Y] - bounds[LOW][Y])*0.5),
(bounds[HIGH][Z] - bounds[LOW][Z])*0.5);
c.x = (bounds[LOW][X] + bounds[HIGH][X])*0.5;
c.y = (bounds[LOW][Y] + bounds[HIGH][Y])*0.5;
c.z = (bounds[LOW][Z] + bounds[HIGH][Z])*0.5;
/*
* Compute position of eye relative to the center of the sphere.
*/
VecSub(Camera.pos, c, &e);
d = VecNormalize(&e);
if (d <= rad)
/*
* Eye is inside sphere.
*/
*near = DEFAULT_NEAR;
else
*near = (d - rad)*0.2;
*far = (d + rad)*2.;
}